package com.oneandone.httpserver.tcp.http;

import org.apache.log4j.Logger;

import com.oneandone.httpserver.tcp.BasicTcpConnectionHandler;
import com.oneandone.httpserver.tcp.BasicTcpListener;
import com.oneandone.httpserver.tcp.http.request.BasicHttpRequestParser;
import com.oneandone.httpserver.tcp.http.request.HttpMethod;
import com.oneandone.httpserver.tcp.http.response.BasicHttpResponseSerializer;
import com.oneandone.httpserver.tcp.http.route.BasicHttpRouter;
import com.oneandone.httpserver.tcp.http.route.RequestHandler;

/**
 * Component used to assemble server components
 * and create a HTTP server based on different options.
 *
 * Usage:
 *
 * Server server = Server.create()
     .workers(w)
     .port(p)
     .keepAlive(ka)
     .route(GET, "/some/url", new SomeRequestHandlerImplementation())
     .route(POST, "/some/other/url", new SomeOtherRequestHandlerImplementation())
     .start();
 *
 * @author cavasilcai
 */
public class Server {
	private static final Logger LOGGER = Logger.getLogger(Server.class); 
	private static BasicTcpListener tcpListener;
	private static BasicTcpConnectionHandler tcpConnectionHandler;
	private static BasicHttpHandler httpHandler;
	private static BasicHttpRouter httpRouter;
	private static BasicHttpRequestParser httpReqParser;
	private static BasicHttpResponseSerializer httpRespSerial;
	private static int nrPort;
	private static int nrWorkers;
	private static boolean keepAlive;
	
    private Server() {
    	
    }

    public static Server create() throws Exception {
    	httpRouter = new BasicHttpRouter();
    	httpReqParser = new BasicHttpRequestParser();
    	httpRespSerial = new BasicHttpResponseSerializer();
    	return new Server();
    }

    public Server port(int port) {
        nrPort = port;
    	return this;
    }

    public Server workers(int workers) {
        nrWorkers = workers;
    	return this;
    }

    public Server route(HttpMethod method, String urlPattern, RequestHandler servler) {
        httpRouter.addRoute(method, urlPattern, servler);
    	return this;
    }

    public Server keepAlive(boolean keepAlive) {
        this.keepAlive = keepAlive;
    	return this;
    }

    public Server start() throws Exception {
    	LOGGER.debug("Server is starting");
    	Exception IllegalStateException = null;
		if (nrPort == 0 || nrWorkers == 0){
        	LOGGER.error("Number port is invalid or number of workers is 0");
			throw IllegalStateException;
		}
		else{
			httpHandler = new BasicHttpHandler(httpRouter,httpRespSerial,httpReqParser);
			tcpConnectionHandler = new BasicTcpConnectionHandler(httpHandler, nrWorkers);
			tcpListener = new BasicTcpListener(tcpConnectionHandler, nrPort);
		}
    	return this;
    }

    public void stop() {
    	LOGGER.debug("Server shutting down");
    	tcpListener.shutdown();
    	LOGGER.debug("Everything shut down succesfully");
    	
    }
}
